package net.ibizsys.eclipse.studio.view;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.ibizsys.eclipse.studio.Activator;
import net.ibizsys.eclipse.studio.console.Console;
import net.ibizsys.eclipse.studio.data.IBizApp;
import net.ibizsys.eclipse.studio.data.IBizSystem;
import net.ibizsys.eclipse.studio.data.LocalDataManager;
import net.ibizsys.eclipse.studio.data.Project;
import net.ibizsys.eclipse.studio.data.ProjectType;
import net.ibizsys.eclipse.studio.file.IBizFileFactory;
import net.ibizsys.eclipse.studio.i18n.I18n;
import net.ibizsys.eclipse.studio.tree.IBizTreeContentProvider;
import net.ibizsys.eclipse.studio.tree.IBizTreeDoubleClickListener;
import net.ibizsys.eclipse.studio.tree.IBizTreeNode;
import net.ibizsys.eclipse.studio.tree.IBizTreeTextLabelProvider;
import net.ibizsys.eclipse.studio.tree.IIBizTreeData;
import net.ibizsys.eclipse.studio.util.StringKit;
import net.ibizsys.eclipse.studio.xml.IBizCodeList;
import net.ibizsys.eclipse.studio.xml.IBizControl;
import net.ibizsys.eclipse.studio.xml.IBizDEACMode;
import net.ibizsys.eclipse.studio.xml.IBizDEAction;
import net.ibizsys.eclipse.studio.xml.IBizDELogic;
import net.ibizsys.eclipse.studio.xml.IBizDEUIAction;
import net.ibizsys.eclipse.studio.xml.IBizDEView;
import net.ibizsys.eclipse.studio.xml.IBizDataQuery;
import net.ibizsys.eclipse.studio.xml.IBizDataset;
import net.ibizsys.eclipse.studio.xml.IBizEntity;
import net.ibizsys.eclipse.studio.xml.IBizFile;
import net.ibizsys.eclipse.studio.xml.IBizFileList;
import net.ibizsys.eclipse.studio.xml.IBizProject;
import net.ibizsys.eclipse.studio.xml.IBizSysProxy;
import net.ibizsys.eclipse.studio.xml.IBizView;
import net.ibizsys.eclipse.studio.xml.IBizWF;
import net.ibizsys.eclipse.studio.xml.IBizWFVersion;
import net.ibizsys.eclipse.studio.xml.XmlNode;

import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.fieldassist.ContentProposalAdapter;
import org.eclipse.jface.fieldassist.IContentProposal;
import org.eclipse.jface.fieldassist.IContentProposalListener;
import org.eclipse.jface.fieldassist.TextContentAdapter;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MenuAdapter;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.ViewPart;

/**
 * 
 * @author <a href='http://www.weibo.com/xjtoo' target='_blank'>Enmaai</a>
 */
public class IBizFunctionView extends ViewPart
{
	private Text searchText;
	private TreeViewer viewer;

	private Map<String, IBizProject> projectMap = new HashMap<String, IBizProject>();
	private IBizSearchProposalProvider searchProposalProvider = new IBizSearchProposalProvider();

	@Override
	public void createPartControl(Composite compsoite)
	{
		compsoite.setLayout(new GridLayout(1, false));
		createToolbar(compsoite);
		createSearchbar(compsoite);

		viewer = new TreeViewer(compsoite, SWT.FILL);
		viewer.getTree().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		viewer.getTree().setMenu(new Menu(viewer.getTree()));

		viewer.setLabelProvider(new DelegatingStyledCellLabelProvider(new IBizTreeTextLabelProvider()));
		viewer.setContentProvider(new IBizTreeContentProvider());
		viewer.addDoubleClickListener(new IBizTreeDoubleClickListener(viewer));

		viewer.getTree().getMenu().addMenuListener(new MenuAdapter()
		{
			public void menuShown(MenuEvent e)
			{
				MenuItem[] items = viewer.getTree().getMenu().getItems();
				for (int i = 0; i < items.length; i++)
				{
					items[i].dispose();
				}
				TreeItem item = viewer.getTree().getSelection()[0];

				Object data = item.getData();

				if (data != null && data instanceof IBizTreeNode)
				{
					IIBizTreeData realData = ((IBizTreeNode) data).getData();

					IBizFileList extList = null;

					if (realData instanceof IBizView)
					{
						for (IBizProject project : projectMap.values())
						{
							if (StringKit.IsEqual(project.getType(), IBizProject.TYPE_SRV, true))
							{
								IBizView view = project.getAppList().findViewById(((IBizView) realData).getId());

								if (view != null)
								{
									extList = view.getFileList();
								}
							}
						}
					}

					renderContextMenu(viewer.getTree().getMenu(), ((XmlNode) realData).getFileList(), extList);
				}
			}
		});

		onRefresh();
	}

	/**
	 * 创建工具栏
	 */
	private void createToolbar(Composite compsoite)
	{
		IActionBars bars = getViewSite().getActionBars();

		Action refreshAction = new Action()
		{
			public void run()
			{
				onRefresh();
			}
		};
		refreshAction.setText("刷新");
		refreshAction.setToolTipText("刷新");
		refreshAction.setImageDescriptor(Activator.GetImageDesc("icons/refresh.png"));
		bars.getToolBarManager().add(refreshAction);

	}

	/**
	 * 创建搜索栏
	 */
	private void createSearchbar(Composite compsoite)
	{
		Composite composite1 = new Composite(compsoite, SWT.NONE);
		composite1.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		GridLayout layout = new GridLayout(1, false);
		layout.marginBottom = 1;
		layout.marginHeight = 0;
		layout.marginWidth = 0;
		layout.marginLeft = 1;
		layout.marginRight = 1;
		layout.marginTop = 1;
		composite1.setBackground(compsoite.getDisplay().getSystemColor(SWT.COLOR_GRAY));
		composite1.setLayout(layout);
		searchText = new Text(composite1, SWT.NONE);
		searchText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		ContentProposalAdapter adapter = new ContentProposalAdapter(searchText, new TextContentAdapter(), searchProposalProvider, null, null);
		adapter.setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_IGNORE);
		adapter.addContentProposalListener(new IContentProposalListener()
		{
			@Override
			public void proposalAccepted(IContentProposal proposal)
			{
				IBizSearchProposal sp = (IBizSearchProposal) proposal;

				if (sp.isPub())
				{
					openFileInEditor(sp.getFile(),sp.getFile().getPubFilePath());
				} else
				{
					confirmAutoCreateAndOpenFile(sp.getFile());
				}
			}
		});
	}

	@Override
	public void setFocus()
	{
		if (this.searchText != null)
		{
			this.searchText.setFocus();
		}
	}

	/**
	 * 刷新
	 */
	private void onRefresh()
	{
		synchronized (this)
		{
			List<IBizTreeNode> datas = new ArrayList<IBizTreeNode>();

			List<IBizSysProxy> list = listProjects();

			if(list.size() == 0)
			{
				Console.println("未获取到有效系统.");
			}	
			
			for (IBizSysProxy sysProxy : list)
			{
				for (IBizProject project : sysProxy.getProjectList())
				{
					projectMap.put(project.getId(), project);
					if (StringKit.IsEqual(project.getType(), IBizProject.TYPE_APP, true))
					{
						datas.add(renderAppNode(project));
					} else if (StringKit.IsEqual(project.getType(), IBizProject.TYPE_SRV, true))
					{
						datas.add(renderModelNode(project));
						// 输出工作流
						datas.add(renderWFNode(project));
					}
				}
			}
			// 输出其他内容<代码表、打印表单、报表等>
			IBizTreeNode otherItem = new IBizTreeNode("[其他]", "icons/file.png");

			for (IBizSysProxy sysProxy : list)
			{
				for (IBizProject project : sysProxy.getProjectList())
				{
					if (StringKit.IsEqual(project.getType(), IBizProject.TYPE_SRV, true))
					{
						// 输出代码表
						IBizTreeNode codeListItem = new IBizTreeNode(project, String.format("[代码表]%1$s", project.getName()));
						otherItem.addChild(codeListItem);

						for (IBizCodeList codeList : project.getCodeList())
						{
							codeListItem.addChild(new IBizTreeNode(codeList));
						}
					}
				}
			}
			datas.add(otherItem);

			this.viewer.setInput(datas);
			this.searchProposalProvider.update(projectMap);
		}
	}

	/**
	 * 输出应用节点
	 * 
	 * @param project
	 */
	private IBizTreeNode renderAppNode(IBizProject project)
	{
		IBizTreeNode root = new IBizTreeNode(project, "[应用]" + project.getCodeName());

		List<IBizView> appviews = project.getViewList().listAppViews();
		if (appviews.size() > 0)
		{
			IBizTreeNode item = new IBizTreeNode(project, "[全局]");
			root.addChild(item);

			for (IBizView view : appviews)
			{
				IBizTreeNode viewItem = new IBizTreeNode(view);
				item.addChild(viewItem);
			}
		}

		for (IBizEntity entity : project.getEntityList())
		{
			IBizTreeNode item = new IBizTreeNode(entity);
			root.addChild(item);

			for (IBizDEView view : project.getViewList().listDEViews(entity.getId()))
			{
				IBizTreeNode viewItem = new IBizTreeNode(view);
				item.addChild(viewItem);

				IBizView view2 = null;

				for (IBizProject project2 : projectMap.values())
				{
					if (StringKit.IsEqual(project2.getType(), IBizProject.TYPE_SRV, true))
					{
						view2 = project2.getAppList().findViewById(view.getId());

						if (view2 != null)
						{
							break;
						}
					}
				}
				if (view2 != null)
				{
					for (IBizControl control : view2.getControls())
					{
						IBizTreeNode ctrlItem = new IBizTreeNode(control);
						viewItem.addChild(ctrlItem);
					}
				}
			}
		}

		return root;
	}

	/**
	 * 输出模型节点
	 * 
	 * @param project
	 */
	private IBizTreeNode renderModelNode(IBizProject project)
	{
		IBizTreeNode root = new IBizTreeNode(project, "[模型]");

		for (IBizEntity entity : project.getEntityList())
		{
			IBizTreeNode entityItem = new IBizTreeNode(entity);

			root.addChild(entityItem);
			// 输出界面行为
			for (IBizDEUIAction data : entity.getUIActionList())
			{
				entityItem.addChild(new IBizTreeNode(data));
			}
			// 输出实体行为
			for (IBizDEAction data : entity.getActionList())
			{
				entityItem.addChild(new IBizTreeNode(data));
			}
			// 输出逻辑
			for (IBizDELogic data : entity.getLogicList())
			{
				entityItem.addChild(new IBizTreeNode(data));
			}
			// 输出自动填充
			for (IBizDEACMode data : entity.getAcmodeList())
			{
				entityItem.addChild(new IBizTreeNode(data));
			}
			// 输出查询模型
			for (IBizDataQuery data : entity.getDataqueryList())
			{
				entityItem.addChild(new IBizTreeNode(data));
			}
			// 输出数据集合
			for (IBizDataset data : entity.getDatasetList())
			{
				entityItem.addChild(new IBizTreeNode(data));
			}
			// PSDEREPORTS
			// PSDEWFS
		}

		return root;
	}

	/**
	 * 输出工作流节点
	 * 
	 * @param project
	 */
	private IBizTreeNode renderWFNode(IBizProject project)
	{
		IBizTreeNode root = new IBizTreeNode(project, "[工作流]");

		for (IBizWF wf : project.getWfList())
		{
			IBizTreeNode wfItem = new IBizTreeNode(wf);
			root.addChild(wfItem);

			for (IBizWFVersion version : wf.getVersionList())
			{
				wfItem.addChild(new IBizTreeNode(version));
			}
		}

		return root;
	}

	/**
	 * 绘制部件右键菜单
	 * 
	 * @param menu
	 * @param fileList
	 */
	private void renderContextMenu(Menu menu, IBizFileList fileList, IBizFileList extList)
	{
		if (fileList != null)
		{
			for (IBizFile file : fileList)
			{
				if (!StringKit.IsBlank(file.getUsrRealFilePath()))
				{
					createMenuItem(menu, "[PUB]" + file.getText(), file, true);
					createMenuItem(menu, "[USR]" + file.getText(), file, false);
				} else
				{
					createMenuItem(menu, file.getText(), file, true);
				}
			}
		}
		if (extList != null)
		{
			for (IBizFile file : extList)
			{
				if (!StringKit.IsBlank(file.getUsrRealFilePath()))
				{
					createMenuItem(menu, "[PUB]" + file.getText(), file, true);
					createMenuItem(menu, "[USR]" + file.getText(), file, false);
				} else
				{
					createMenuItem(menu, file.getText(), file, true);
				}
			}
		}
	}

	/**
	 * 创建菜单选项
	 * 
	 * @param menu
	 * @param text
	 * @param icon
	 * @param data
	 * @param bPub
	 * @return
	 */
	private MenuItem createMenuItem(Menu menu, String text, IBizFile data, final boolean bPub)
	{
		MenuItem newItem = new MenuItem(menu, SWT.NONE);
		newItem.setText(text);
		newItem.setImage(Activator.GetImage(data.getType().icon()));
		newItem.setData(data);

		newItem.addListener(SWT.Selection, new Listener()
		{
			public void handleEvent(Event e)
			{
				IBizFile file = (IBizFile) e.widget.getData();
				if (bPub)
				{
					openFileInEditor(file,file.getPubFilePath());
				} else
				{
					confirmAutoCreateAndOpenFile(file);
				}
			}
		});
		return newItem;
	}

	/**
	 * 提示用户是否创建并打开文件
	 * 
	 * @param file
	 */
	protected void confirmAutoCreateAndOpenFile(IBizFile file)
	{
		File ioFile = new File(file.getUsrRealFilePath());
		if (ioFile.exists())
		{
			openFileInEditor(file,file.getUsrRealFilePath());
		} else
		{
			if (MessageDialog.openConfirm(getSite().getShell(), I18n.Info, I18n.UsrConfirm))
			{
				if (!IBizFileFactory.create(file))
				{
					Console.println("无法创建用户文件[" + file.getUsrRealFilePath() + "]");
					return;
				}
				refreshProjectAndOpenFile(file,file.getProject().getUsrPRJName(), file.getUsrRealFilePath());
			}
		}
	}

	/**
	 * 列举全部系统
	 * 
	 * @return
	 */
	private List<IBizSysProxy> listProjects()
	{
		List<IBizSysProxy> sysProxyList = new ArrayList<IBizSysProxy>();

		for (IBizSystem system : LocalDataManager.manager().listLocalSystems(true))
		{
			IBizSysProxy sysProxy = new IBizSysProxy(system);

			sysProxy.addProjects(loadProjects(system.getProjects(), sysProxy));

			for (IBizApp app : system.getApps())
			{
				sysProxy.addProjects(loadProjects(app.getProjects(), sysProxy));
			}

			if (sysProxy.getProjectList().size() > 0)
			{
				sysProxyList.add(sysProxy);
			} else
			{
				Console.println("系统[" + sysProxy.getName() + "]不存在任何模型配置文件.");
			}
		}

		return sysProxyList;
	}

	/**
	 * 加载项目的模型配置文件
	 * 
	 * @param projects
	 * @param system
	 * @return
	 */
	private List<IBizProject> loadProjects(List<Project> projects, IBizSysProxy system)
	{
		List<IBizProject> list = new ArrayList<IBizProject>();

		for (Project proj : projects)
		{
			if (proj.getType() == ProjectType.SRVPUB || proj.getType() == ProjectType.APPPUB)
			{
				File file = new File(Activator.getDefault().getRootPath() + File.separator + proj.getName() + File.separator + ".ibizproject");

				if (file.exists())
				{
					IBizProject project = IBizProject.loadXmlFile(file, system);

					if (project != null)
					{
						list.add(project);
					} else
					{
						Console.println("项目[" + proj.getName() + "]模型配置文件[.ibizproject]解析失败.");
					}
				} else
				{
					Console.println("项目[" + proj.getName() + "]中不存在[.ibizproject]模型配置文件.");
				}
			}
		}

		return list;
	}

	/**
	 * 在编辑器中打开文件
	 * 
	 * @param fileToOpen
	 * @return
	 */
	public boolean openFileInEditor(IBizFile ibizFile,String fileToOpen)
	{
		//判断文件是否是ng的controller
				
		File file = new File(fileToOpen);
		if (file.isFile())
		{
			IFileStore fileStore = EFS.getLocalFileSystem().getStore(file.toURI());
			IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
			if (page == null)
			{
				return false;
			}
			try
			{
				IDE.openEditorOnFileStore(page, fileStore);
			} catch (PartInitException e)
			{
				return false;
			}
		} else
		{
			return false;
		}
		return true;
	}

	public void refreshProjectAndOpenFile(final IBizFile ibizFile,final String projectName, final String fileToOpen)
	{
		try
		{
			new ProgressMonitorDialog(getSite().getShell()).run(true, true, new IRunnableWithProgress()
			{
				@Override
				public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException
				{
					IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);

					if (project != null)
					{
						try
						{
							project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
						} catch (CoreException e)
						{
							Console.println("[错误]刷新项目项目[" + projectName + "]失败.");
						}
					} else
					{
						Console.println("[错误]获取项目[" + projectName + "]失败,无法刷新项目.");
					}
					openFileInEditor(ibizFile,fileToOpen);
				}
			});
		} catch (Exception e)
		{
			Console.println("[错误]获取项目执行线程异常,无法导入项目,导入项目终止,无法刷新项目[" + projectName + "].");

			openFileInEditor(ibizFile,fileToOpen);
		}
	}
}
